#include	"lp_global_vars.h"
#include	"config_parser.h"

struct timeval startTime_Total, endTime_Total, end, start, elapsedTime_Total, performance_start_time, performance_end_time, elapsedTime_Interval, tv1;
struct event *print_stat_timeout_eve, *socketEv1, *socketEv2;

bool f = false, r_tag = false;
char lostPackets_fileName[STRING_SIZE];

int learnerID, proposerID;
int lowestDelivered = -1;

int proposer_to_acceptor_0_sid, SUBMIT_PER_WAKE, MSG_ID = 0, digit = 0;

inst *data;
inst *new_data;
int learner_to_acceptor_sid;

const char * config_path;

//------------------------------------------------------------------------------
void initialize_events();
void initialize_buffers();
void validate_parameters(int argc, const char *argv[]);
//------------------------------------------------------------------------------
int main(int argc, const char *argv[]) {
	//---------------------Variables--------------------------------------------
	int status;
	//--------------------------------------------------------------------------
	initialize_events();
	validate_parameters(argc, argv);
	//--------------------------------------------------------------------------
	parse_configuration(config_path, -1, proposerID, learnerID);
	learner_to_acceptor_sid = GET_LEARNER_SID_TCP_TO_ACCEPTOR(learnerID);//create_tcp_client_socket(atoi(learner_port[1]),learner_ip[1]);
	//==========================================================================
	initialize_buffers();
	printf("-----------------------------------------------------------\n");
	event_init();
	//---------------------------------Events-----------------------------------
	event_set(socketEv1, get_config_info()->learner_infos[get_config_info()->self_learner_id].self_sid, EV_READ | EV_PERSIST, recv_new_packet_from_predecessor, NULL);
	status = event_add(socketEv1, NULL);
	assert(status >= 0);
	//==========================================================================
	event_set(socketEv2, learner_to_acceptor_sid, EV_READ | EV_PERSIST, recv_lost_packet, NULL);
	status = event_add(socketEv2, NULL);
	assert(status >= 0);
	//==========================================================================
	evtimer_set(print_stat_timeout_eve, compute_performance, print_stat_timeout_eve); //for both the learner and the proposer
	status = evtimer_add(print_stat_timeout_eve, &tv1);
	assert(status >= 0);
	//==========================================================================
	event_dispatch();

	close(proposer_to_acceptor_0_sid);
	exit(0);
}
//------------------------------------------------------------------------------
void initialize_events() {
	tv1.tv_sec = 1;
	tv1.tv_usec = 0;

	socketEv1 = (struct event*) malloc(sizeof(struct event));
	socketEv2 = (struct event*) malloc(sizeof(struct event));
	print_stat_timeout_eve = (struct event*) malloc(sizeof(struct event));
}
//------------------------------------------------------------------------------
void initialize_buffers() {

	N = get_config_info()->total_num_acceptors;

	lp_interval_performance = malloc(sizeof(lp_performance));
	lp_next_performance_index = 0;
	lp_nulify_performance(lp_interval_performance);

	int i;
	data = (inst*) malloc(sizeof(inst) * INTERNAL_BUFFER_SIZE);

		for (i = 0; i < INTERNAL_BUFFER_SIZE; i++) {
			data[(i % INTERNAL_BUFFER_SIZE)].deliver = false;
			data[(i % INTERNAL_BUFFER_SIZE)].received = false;
			data[(i % INTERNAL_BUFFER_SIZE)].highestDeliverable = -1;
			data[(i % INTERNAL_BUFFER_SIZE)].packet.pack_id = -1;
			data[(i % INTERNAL_BUFFER_SIZE)].packet.p_msgs[0].msg_id = 0;
		}
	new_data = (inst*) malloc(sizeof(inst));
	gettimeofday(&start, NULL);
	gettimeofday(&startTime_Total, NULL);
	gettimeofday(&performance_start_time, NULL);
}
//------------------------------------------------------------------------------
void validate_parameters(int argc, const char *argv[]) {
	if (argc != 4) {
		printf("Incompatible call to this function. Try Again.!\n1. learnerID.\n2. Config Path\n6. File to store the performance\n");
		exit(-1);
	} else {

		learnerID = atoi(argv[1]);
		config_path = argv[2];
		lp_performance_file = argv[3];

	}
}

